package gui;

import graphics.CanvasSlicePlotter;
import gui.*;
import java.awt.Color;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import kernel.loaders.STLFileLoader;
import kernel.loaders.exception.InvalidCodificationTypeException;
import kernel.printing.PrintableTest;
import kernel.stl.STL;
import kernel.stl.exception.InvalidZIndexException;
import kernel.stl.exception.UndefinedPointException;
import kernel.stl.slicing.Slice;
import kernel.stl.slicing.Slicer;

/**
 *
 * @author  George
 */
public class MainJFrame extends javax.swing.JFrame {

    private STL stl;
    private static final String DEFAULT_BASE_FRAME_TITLE = "STL Slicing Tool";
    private int sliceIndex = 0;
    private int sliceCount = 100;
    private Slice currentSlice;
    private CanvasSlicePlotter canvasPlotter;
    private double spacingBetweenSlices;
    
    final double SLICE_MEASURE_CONSTANT = 8.825;

    private void updateSpacingBetweenSlices() {
        int count = Math.round(Float.parseFloat(this.sliceCountTextField.getText()));
        
        this.setSliceCount(count);

        double width = this.stl.getSolid().getMaxX() - this.stl.getSolid().getMinX();
        double depth = this.stl.getSolid().getMaxY() - this.stl.getSolid().getMinY();
        double heigth = this.stl.getSolid().getMaxZ() - this.stl.getSolid().getMinZ();

        double maximum;

        if (width > depth) {
            maximum = width;
        } else {
            maximum = depth;
        }
        double prototypeHeigth = depth / maximum * SLICE_MEASURE_CONSTANT;

        double spacing = prototypeHeigth / this.sliceCount;
        
        this.jTextFieldSpacing.setText(Double.toString(spacing));
    }

    private void updateSliceCountBySpacing() {
        double spacing = Double.parseDouble(this.jTextFieldSpacing.getText());        

        double width = this.stl.getSolid().getMaxX() - this.stl.getSolid().getMinX();
        double depth = this.stl.getSolid().getMaxY() - this.stl.getSolid().getMinY();
        double heigth = this.stl.getSolid().getMaxZ() - this.stl.getSolid().getMinZ();

        double maximum;

        if (width > depth) {
            maximum = width;
        } else {
            maximum = depth;
        }
        
        double prototypeHeigth = depth / maximum * SLICE_MEASURE_CONSTANT;
        
        setSliceCount((int) Math.round(prototypeHeigth / spacing));
        
        this.sliceCountTextField.setText(Float.toString(this.sliceCount));
        //spacing = prototypeHeigth / this.sliceCount;
        
    }
    
    private void setVersion(String version) {
        this.jLabelVersion.setText(version);
    }

    private void goToTheNextSlice() {
        if (this.sliceCount - 1 > this.sliceIndex) {
            this.sliceIndex = this.sliceIndex + 1;
            refreshCurrentSlice();
        }
    }

    private void goToThePreviousSlice() {
        if (this.sliceIndex > 0) {
            this.sliceIndex = this.sliceIndex - 1;
            refreshCurrentSlice();
        }
    }

    private void goToTheFirstSlice() {
        if (this.sliceCount > 0) {
            this.sliceIndex = 0;
            refreshCurrentSlice();
        }
    }

    private void goToTheLastSlice() {
        if (this.sliceCount > 0) {
            this.sliceIndex = sliceCount - 1;
            refreshCurrentSlice();
        }
    }

    private void setSliceIndex(int sliceIndex) {
        if (this.sliceCount > 0 && sliceIndex >= 0 && sliceIndex < sliceCount) {
            this.sliceIndex = sliceIndex;
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

    private void refreshWorkspace() {
        if (stl != null) {
            stlPropertiesTextArea.setText(stl.getSTLProperties());

            this.sliceCountTextField.setText("100");
            this.sliceCountTextField.setEnabled(true);
            this.sliceIndexTextField.setText("0");
            this.sliceIndexTextField.setEnabled(true);
            this.scaleTextField.setEnabled(true);
            this.setTitle(stl.getFileName() + " - " + DEFAULT_BASE_FRAME_TITLE);
            this.generateSlice.setEnabled(true);
            this.firstButton.setEnabled(true);
            this.previousButton.setEnabled(true);
            this.nextButton.setEnabled(true);
            this.lastButton.setEnabled(true);

            this.jComboBoxSliceColor.setEnabled(true);

            this.keepTrailCheckBox.setEnabled(true);
            this.fillSlicesCheckBox.setEnabled(true);
            this.jButtonPrint.setEnabled(true);

            //this.clearSliceButton.setEnabled(true);
            this.showObjectButton.setEnabled(true);

            this.sliceCountTextField.setText(String.valueOf(this.sliceCount));
            this.sliceIndexTextField.setText(String.valueOf(this.sliceIndex));

            this.scaleTextField.setText("0");
            refreshCurrentSlice();
            updateSpacingBetweenSlices();
            
            this.jButtonAdjustSliceCount.setEnabled(true);
            this.jButtonAdjustSpacing.setEnabled(true);

            this.jButtonExchangeXYAxis.setEnabled(true);
            this.jButtonExchangeXZAxis.setEnabled(true);
            this.jButtonExchangeYZAxis.setEnabled(true);
            

        } else {
            this.stlPropertiesTextArea.setText("");

            this.sliceCountTextField.setText("");
            this.sliceCountTextField.setEnabled(false);
            this.sliceIndexTextField.setText("");
            this.sliceIndexTextField.setEnabled(false);
            this.scaleTextField.setText("0");
            this.scaleTextField.setEnabled(false);
            this.setTitle(DEFAULT_BASE_FRAME_TITLE);
            this.generateSlice.setEnabled(false);
            this.firstButton.setEnabled(false);
            this.previousButton.setEnabled(false);
            this.nextButton.setEnabled(false);
            this.lastButton.setEnabled(false);

            this.sliceCountTextField.setText("100");
            this.sliceIndexTextField.setText("0");

            this.jComboBoxSliceColor.setEnabled(false);

            this.fillSlicesCheckBox.setEnabled(false);
            this.jButtonPrint.setEnabled(false);

            this.keepTrailCheckBox.setSelected(false);
            this.keepTrailCheckBox.setEnabled(false);
            //this.clearSliceButton.setEnabled(false);
            this.showObjectButton.setEnabled(false);
            this.scaleTextField.setText("0");

            this.jButtonExchangeXYAxis.setEnabled(false);
            this.jButtonExchangeXZAxis.setEnabled(false);
            this.jButtonExchangeYZAxis.setEnabled(false);
            
            this.jButtonAdjustSliceCount.setEnabled(false);
            this.jButtonAdjustSpacing.setEnabled(false);
        }
    }
    
    private void refreshCurrentSlice() {
        if (sliceIndex == 0 && sliceCount == 0) {
            this.currentSlice = null;
            return;
        }
        double deltaZ = this.stl.getSolid().getMaxZ() - this.stl.getSolid().getMinZ();
        double zIndex = stl.getSolid().getMinZ() + (double) sliceIndex / (double) (sliceCount - 1) * deltaZ;

        Slicer slicer = new Slicer(this.stl);

        try {
            this.currentSlice = slicer.slicing(zIndex);
        } catch (InvalidZIndexException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UndefinedPointException ex) {
            Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void setSliceCount(int sliceCount) {
        this.sliceCount = sliceCount;
    }

    private Color colorFromString(String str) {
        if (str.equalsIgnoreCase("Preto")) {
            return Color.BLACK;
        } else if (str.equalsIgnoreCase("Vermelho")) {
            return Color.RED;
        } else if (str.equalsIgnoreCase("Azul")) {
            return Color.BLUE;
        } else if (str.equalsIgnoreCase("Verde")) {
            return Color.GREEN;
        } else {
            return Color.BLACK;
        }
    }

    private void plotSlice(boolean keepTrail) {
        if (sliceIndex == 0 && sliceCount == 0) {
            return;
        }

        refreshCurrentSlice();

        canvasPlotter.setSTL(stl);
        canvasPlotter.setFillSlices(this.fillSlicesCheckBox.isSelected());

        String str = (String) this.jComboBoxSliceColor.getSelectedItem();

        canvasPlotter.setFillColor(this.colorFromString(str));

        if (!keepTrail) {
            this.canvasPlotter.getGraphics().clearRect(0, 0, 600, 600);
        }
        canvasPlotter.setSlice(currentSlice);
        canvasPlotter.paint(this.canvasPlotter.getGraphics());
    }

    /** Creates new form MainJFrame */
    public MainJFrame() {

        initComponents();

        this.canvasPlotter = new CanvasSlicePlotter();
        sliceInternalFrame.add(this.canvasPlotter);
        this.canvasPlotter.setSize(540, 540);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fileNameTextField = new javax.swing.JTextField();
        searchButton = new javax.swing.JButton();
        scaleTextField = new javax.swing.JTextField();
        scaleLabel = new javax.swing.JLabel();
        jComboBox1 = new javax.swing.JComboBox();
        jLabel2 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        loadSTLButton = new javax.swing.JButton();
        showObjectButton = new javax.swing.JButton();
        stlProperties = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        stlPropertiesTextArea = new javax.swing.JTextArea();
        jSeparator2 = new javax.swing.JSeparator();
        generateSlice = new javax.swing.JButton();
        sliceCountLabel = new javax.swing.JLabel();
        sliceCountTextField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        sliceIndexTextField = new javax.swing.JTextField();
        stlFileName = new javax.swing.JLabel();
        slicingLabel = new javax.swing.JLabel();
        showObjectLabel = new javax.swing.JLabel();
        keepTrailCheckBox = new javax.swing.JCheckBox();
        firstButton = new javax.swing.JButton();
        previousButton = new javax.swing.JButton();
        nextButton = new javax.swing.JButton();
        lastButton = new javax.swing.JButton();
        jButtonPrint = new javax.swing.JButton();
        sliceInternalFrame = new javax.swing.JInternalFrame();
        fillSlicesCheckBox = new javax.swing.JCheckBox();
        jLabelVersion = new javax.swing.JLabel();
        jComboBoxSliceColor = new javax.swing.JComboBox();
        jLabelSliceColor = new javax.swing.JLabel();
        jLabelSpacing = new javax.swing.JLabel();
        jTextFieldSpacing = new javax.swing.JTextField();
        jButtonAdjustSpacing = new javax.swing.JButton();
        jButtonAdjustSliceCount = new javax.swing.JButton();
        jButtonExchangeXYAxis = new javax.swing.JButton();
        jButtonExchangeXZAxis = new javax.swing.JButton();
        jButtonExchangeYZAxis = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("STL Slicing Tool");
        setResizable(false);

        fileNameTextField.setName("fileNameTextField"); // NOI18N

        searchButton.setText("Procurar");
        searchButton.setName("searchFile"); // NOI18N
        searchButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchButtonActionPerformed(evt);
            }
        });

        scaleTextField.setText("0");
        scaleTextField.setName("jTextFieldScale"); // NOI18N
        scaleTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                scaleTextFieldActionPerformed(evt);
            }
        });

        scaleLabel.setText("Escala");

        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ASCII", "Binário" }));

        jLabel2.setText("Codificação:");

        loadSTLButton.setText("Carregar");
        loadSTLButton.setName("loadSTL"); // NOI18N
        loadSTLButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadSTLButtonActionPerformed(evt);
            }
        });

        showObjectButton.setText("Mostrar Objeto");
        showObjectButton.setName("showObject"); // NOI18N
        showObjectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showObjectButtonActionPerformed(evt);
            }
        });

        stlProperties.setText("Propriedades do STL");

        stlPropertiesTextArea.setColumns(20);
        stlPropertiesTextArea.setEditable(false);
        stlPropertiesTextArea.setRows(5);
        stlPropertiesTextArea.setDragEnabled(true);
        jScrollPane1.setViewportView(stlPropertiesTextArea);

        generateSlice.setText("Gerar Fatia");
        generateSlice.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                generateSliceActionPerformed(evt);
            }
        });

        sliceCountLabel.setText("Número de fatias:");

        sliceCountTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sliceCountTextFieldActionPerformed(evt);
            }
        });
        sliceCountTextField.addInputMethodListener(new java.awt.event.InputMethodListener() {
            public void caretPositionChanged(java.awt.event.InputMethodEvent evt) {
            }
            public void inputMethodTextChanged(java.awt.event.InputMethodEvent evt) {
                sliceCountTextFieldInputMethodTextChanged(evt);
            }
        });

        jLabel1.setText("Índice da fatia:");

        sliceIndexTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sliceIndexTextFieldActionPerformed(evt);
            }
        });
        sliceIndexTextField.addInputMethodListener(new java.awt.event.InputMethodListener() {
            public void caretPositionChanged(java.awt.event.InputMethodEvent evt) {
            }
            public void inputMethodTextChanged(java.awt.event.InputMethodEvent evt) {
                sliceIndexTextFieldInputMethodTextChanged(evt);
            }
        });

        stlFileName.setText("Arquivo:");

        slicingLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
        slicingLabel.setText("Fatiamento:");

        showObjectLabel.setFont(new java.awt.Font("Tahoma", 1, 14));
        showObjectLabel.setText("Visualização:");

        keepTrailCheckBox.setText("Manter rastro");

        firstButton.setText("<<");
        firstButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                firstButtonActionPerformed(evt);
            }
        });

        previousButton.setText("<");
        previousButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                previousButtonActionPerformed(evt);
            }
        });

        nextButton.setText(">");
        nextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextButtonActionPerformed(evt);
            }
        });

        lastButton.setText(">>");
        lastButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lastButtonActionPerformed(evt);
            }
        });

        jButtonPrint.setText("Imprimir");
        jButtonPrint.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonPrintActionPerformed(evt);
            }
        });

        sliceInternalFrame.setVisible(true);
        sliceInternalFrame.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentMoved(java.awt.event.ComponentEvent evt) {
                sliceInternalFrameComponentMoved(evt);
            }
        });

        javax.swing.GroupLayout sliceInternalFrameLayout = new javax.swing.GroupLayout(sliceInternalFrame.getContentPane());
        sliceInternalFrame.getContentPane().setLayout(sliceInternalFrameLayout);
        sliceInternalFrameLayout.setHorizontalGroup(
            sliceInternalFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 593, Short.MAX_VALUE)
        );
        sliceInternalFrameLayout.setVerticalGroup(
            sliceInternalFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 622, Short.MAX_VALUE)
        );

        fillSlicesCheckBox.setSelected(true);
        fillSlicesCheckBox.setLabel("Preencher");

        jLabelVersion.setFont(new java.awt.Font("Tahoma", 1, 14));
        jLabelVersion.setText("Versão: ");

        jComboBoxSliceColor.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Preto", "Vermelho", "Azul", "Verde" }));

        jLabelSliceColor.setText("Cor da fatia");

        jLabelSpacing.setText("Espaçamento:");

        jButtonAdjustSpacing.setText("Ajustar espaçamento");
        jButtonAdjustSpacing.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAdjustSpacingActionPerformed(evt);
            }
        });

        jButtonAdjustSliceCount.setText("Ajustar número de fatias");
        jButtonAdjustSliceCount.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAdjustSliceCountActionPerformed(evt);
            }
        });

        jButtonExchangeXYAxis.setText("X <-> Y");
        jButtonExchangeXYAxis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonExchangeXYAxisActionPerformed(evt);
            }
        });

        jButtonExchangeXZAxis.setText("X <-> Z");
        jButtonExchangeXZAxis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonExchangeXZAxisActionPerformed(evt);
            }
        });

        jButtonExchangeYZAxis.setText("Y<->Z");
        jButtonExchangeYZAxis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonExchangeYZAxisActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(stlProperties)
                    .addComponent(slicingLabel)
                    .addComponent(jLabelVersion)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(stlFileName)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(searchButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(loadSTLButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jButtonAdjustSliceCount, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(sliceCountLabel)
                                    .addComponent(jLabelSpacing))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(jTextFieldSpacing)
                                    .addComponent(sliceCountTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)))
                            .addComponent(jButtonAdjustSpacing, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(70, 70, 70))
                    .addComponent(showObjectButton)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(scaleLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(scaleTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(showObjectLabel)
                    .addComponent(fillSlicesCheckBox)
                    .addComponent(keepTrailCheckBox)
                    .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                            .addComponent(jLabelSliceColor)
                            .addGap(24, 24, 24)
                            .addComponent(jComboBoxSliceColor, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                            .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(sliceIndexTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(jButtonPrint, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                            .addComponent(firstButton, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(previousButton)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(nextButton)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(lastButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addComponent(generateSlice, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 206, Short.MAX_VALUE))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 254, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButtonExchangeXYAxis)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonExchangeXZAxis)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonExchangeYZAxis)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sliceInternalFrame, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(sliceInternalFrame)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabelVersion)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(stlFileName)
                            .addComponent(fileNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(searchButton))
                        .addGap(4, 4, 4)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel2)
                            .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(loadSTLButton))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(1, 1, 1)
                        .addComponent(stlProperties)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButtonExchangeXYAxis)
                            .addComponent(jButtonExchangeXZAxis)
                            .addComponent(jButtonExchangeYZAxis))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(slicingLabel)
                        .addGap(12, 12, 12)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(sliceCountLabel)
                            .addComponent(sliceCountTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelSpacing)
                            .addComponent(jTextFieldSpacing, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(1, 1, 1)
                                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(layout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(jButtonAdjustSpacing)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonAdjustSliceCount)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelSliceColor)
                            .addComponent(jComboBoxSliceColor, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel1)
                            .addComponent(sliceIndexTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(generateSlice)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(firstButton)
                            .addComponent(previousButton)
                            .addComponent(nextButton)
                            .addComponent(lastButton))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(keepTrailCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(fillSlicesCheckBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButtonPrint)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(showObjectLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(scaleLabel)
                            .addComponent(scaleTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(showObjectButton)))
                .addContainerGap())
        );

        fileNameTextField.getAccessibleContext().setAccessibleName("fileNameTextField");
        showObjectButton.getAccessibleContext().setAccessibleName("ShowObject");
        stlFileName.getAccessibleContext().setAccessibleName("stlFileNameTextField");
        slicingLabel.getAccessibleContext().setAccessibleName(null);
        jLabelSpacing.getAccessibleContext().setAccessibleName("");

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
// TODO add your handling code here:
    JFileChooser fileChooser = new JFileChooser();
    int returnValue = fileChooser.showOpenDialog(this);
    if (returnValue == JFileChooser.APPROVE_OPTION) {
        fileNameTextField.setText(fileChooser.getSelectedFile().getAbsolutePath());
    }
}//GEN-LAST:event_searchButtonActionPerformed

private void showObjectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showObjectButtonActionPerformed
// TODO add your handling code here:
    String fileName = fileNameTextField.getText();
    Double scale = Double.parseDouble(scaleTextField.getText());
    Object3DFrame frame = new Object3DFrame(stl, scale);
    frame.setTitle(fileName);
}//GEN-LAST:event_showObjectButtonActionPerformed

private void scaleTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scaleTextFieldActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_scaleTextFieldActionPerformed

private void loadSTLButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadSTLButtonActionPerformed
// TODO add your handling code here:
    String fileName = fileNameTextField.getText();
    STLFileLoader stlFileLoader = new STLFileLoader();
    int codificationType = this.jComboBox1.getSelectedIndex();
    try {
        this.stl = stlFileLoader.load(fileName, codificationType);
    } catch (IOException ioException) {
        System.out.println("ErioExceptionro na leitura do arquivo " + fileName);
    } catch (InvalidCodificationTypeException invalidCodificationTypeExcetion) {
        System.out.println("Tipo de codificação inválido: " + codificationType);
    }
    refreshWorkspace();
    updateSpacingBetweenSlices();
}//GEN-LAST:event_loadSTLButtonActionPerformed

private void generateSliceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_generateSliceActionPerformed
// TODO add your handling code here:       
    int sliceCount = 0;
    int sliceIndex = 0;

    try {
        sliceCount = Integer.parseInt(this.sliceCountTextField.getText());
    } catch (NumberFormatException ex) {
        JOptionPane.showMessageDialog(this, "Digite um número válido de " +
                "camadas.");
        return;
    }

    try {
        sliceIndex = Integer.parseInt(this.sliceIndexTextField.getText());
    } catch (NumberFormatException ex) {
        JOptionPane.showMessageDialog(this, "Digite um número válido de " +
                "fatias.");
        return;
    }

    if ((sliceIndex >= sliceCount) || (sliceIndex < 0)) {
        JOptionPane.showMessageDialog(this, "O índice da fatia deve ser " +
                "menor que o número total de fatias.");
        return;
    }

    this.setSliceCount(sliceCount);
    this.setSliceIndex(sliceIndex);

    plotSlice(this.keepTrailCheckBox.isSelected());
}//GEN-LAST:event_generateSliceActionPerformed

private void previousButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousButtonActionPerformed
// TODO add your handling code here:
    goToThePreviousSlice();
    refreshWorkspace();
    plotSlice(this.keepTrailCheckBox.isSelected());
}//GEN-LAST:event_previousButtonActionPerformed

private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
// TODO add your handling code here:
    goToTheNextSlice();
    refreshWorkspace();
    plotSlice(this.keepTrailCheckBox.isSelected());
}//GEN-LAST:event_nextButtonActionPerformed

private void firstButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_firstButtonActionPerformed
// TODO add your handling code here:
    goToTheFirstSlice();
    refreshWorkspace();
    plotSlice(this.keepTrailCheckBox.isSelected());
}//GEN-LAST:event_firstButtonActionPerformed

private void lastButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lastButtonActionPerformed
// TODO add your handling code here:    
    goToTheLastSlice();
    refreshWorkspace();
    plotSlice(this.keepTrailCheckBox.isSelected());
}//GEN-LAST:event_lastButtonActionPerformed

private void sliceIndexTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sliceIndexTextFieldActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_sliceIndexTextFieldActionPerformed

private void jButtonPrintActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonPrintActionPerformed
// TODO add your handling code here:
    PrinterJob job = PrinterJob.getPrinterJob();
    PrintableTest printable = new PrintableTest(this.canvasPlotter);

    job.setPrintable(printable);
    try {
        job.print();
    } catch (PrinterException ex) {
        Logger.getLogger(MainJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }
}//GEN-LAST:event_jButtonPrintActionPerformed

private void sliceInternalFrameComponentMoved(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_sliceInternalFrameComponentMoved
// TODO add your handling code here:
    this.sliceInternalFrame.setLocation(310, 11);
}//GEN-LAST:event_sliceInternalFrameComponentMoved

private void sliceCountTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sliceCountTextFieldActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_sliceCountTextFieldActionPerformed

private void sliceCountTextFieldInputMethodTextChanged(java.awt.event.InputMethodEvent evt) {//GEN-FIRST:event_sliceCountTextFieldInputMethodTextChanged
// TODO add your handling code here:
    try {
        this.setSliceCount(Integer.parseInt(this.sliceCountTextField.getText()));
        this.updateSpacingBetweenSlices();
    } catch (NumberFormatException ex) {
    }
}//GEN-LAST:event_sliceCountTextFieldInputMethodTextChanged

private void jButtonAdjustSpacingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAdjustSpacingActionPerformed
// TODO add your handling code here:
    this.updateSpacingBetweenSlices();
//GEN-LAST:event_jButtonAdjustSpacingActionPerformed
}

private void jButtonAdjustSliceCountActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAdjustSliceCountActionPerformed
// TODO add your handling code here:
    this.updateSliceCountBySpacing();//GEN-LAST:event_jButtonAdjustSliceCountActionPerformed
}                                                       

private void jButtonExchangeXYAxisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonExchangeXYAxisActionPerformed
// TODO add your handling code here:
    this.stl.getSolid().exchangeXYAxis();//GEN-LAST:event_jButtonExchangeXYAxisActionPerformed
}                                                     

private void jButtonExchangeXZAxisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonExchangeXZAxisActionPerformed
// TODO add your handling code here:
    this.stl.getSolid().exchangeXZAxis();    
}//GEN-LAST:event_jButtonExchangeXZAxisActionPerformed

private void jButtonExchangeYZAxisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonExchangeYZAxisActionPerformed
// TODO add your handling code here:
    this.stl.getSolid().exchangeYZAxis();
}//GEN-LAST:event_jButtonExchangeYZAxisActionPerformed

private void sliceIndexTextFieldInputMethodTextChanged(java.awt.event.InputMethodEvent evt) {//GEN-FIRST:event_sliceIndexTextFieldInputMethodTextChanged
    // TODO add your handling code here:
    try {//GEN-LAST:event_sliceIndexTextFieldInputMethodTextChanged
            this.setSliceIndex(Integer.parseInt(this.sliceIndexTextField.getText()));
        } catch (NumberFormatException ex) {
            System.out.println("Índice inválido");
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                MainJFrame frame = new MainJFrame();
                frame.setVisible(true);
                frame.refreshWorkspace();
                frame.setVersion(VersionControl.currentVersion());
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField fileNameTextField;
    private javax.swing.JCheckBox fillSlicesCheckBox;
    private javax.swing.JButton firstButton;
    private javax.swing.JButton generateSlice;
    private javax.swing.JButton jButtonAdjustSliceCount;
    private javax.swing.JButton jButtonAdjustSpacing;
    private javax.swing.JButton jButtonExchangeXYAxis;
    private javax.swing.JButton jButtonExchangeXZAxis;
    private javax.swing.JButton jButtonExchangeYZAxis;
    private javax.swing.JButton jButtonPrint;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JComboBox jComboBoxSliceColor;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabelSliceColor;
    private javax.swing.JLabel jLabelSpacing;
    private javax.swing.JLabel jLabelVersion;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JTextField jTextFieldSpacing;
    private javax.swing.JCheckBox keepTrailCheckBox;
    private javax.swing.JButton lastButton;
    private javax.swing.JButton loadSTLButton;
    private javax.swing.JButton nextButton;
    private javax.swing.JButton previousButton;
    private javax.swing.JLabel scaleLabel;
    private javax.swing.JTextField scaleTextField;
    private javax.swing.JButton searchButton;
    private javax.swing.JButton showObjectButton;
    private javax.swing.JLabel showObjectLabel;
    private javax.swing.JLabel sliceCountLabel;
    private javax.swing.JTextField sliceCountTextField;
    private javax.swing.JTextField sliceIndexTextField;
    private javax.swing.JInternalFrame sliceInternalFrame;
    private javax.swing.JLabel slicingLabel;
    private javax.swing.JLabel stlFileName;
    private javax.swing.JLabel stlProperties;
    private javax.swing.JTextArea stlPropertiesTextArea;
    // End of variables declaration//GEN-END:variables
}
